Set-up packages // libraries and prepare for data import:
## Uncomment install.packages and run outside of notebook environment:
## install.packages(c("psych" ,"xtable", "tidyverse", "jsonlite", "likert", "ggplot2", "ploty", "mosaic"))
library(psych)
library(likert)
library(jsonlite)
library(ggplot2)
library(mosaic)
library(plotly)
source("http://pcwww.liv.ac.uk/~william/R/crosstab.r")
theme_set(theme_classic())
Set-up directories, import and clean data:
rm(list=ls())
setwd("/Users/allieblaising/desktop/bang/R")
getwd()
[1] "/Users/allieblaising/Desktop/bang/R"
dataPath = "../.data"
## Define function to extract survey results:
extractSurvey = function(frame,survey) {
rounds = seq(1,length(frame$results.format[[1]]))
roundResponses = lapply(rounds, function(round) {
getCol = paste("results.",survey,".",round, sep="")
surveyCols = Filter(function(x) grepl(getCol,x),names(frame))
newCols = lapply(surveyCols, function(x) gsub(getCol,paste("results.",survey, sep=""),x) )
surveyFrame = frame[,surveyCols]
if (is.null(newCols)) {return("No newCols")}
names(surveyFrame) = newCols
surveyFrame$id = frame$id
surveyFrame$round = round
surveyFrame$batch = frame$batch
surveyFrame$rooms = frame$rooms
surveyFrame$manipulation = frame$results.manipulationCheck
surveyFrame$blacklist = frame$results.blacklistCheck
return(surveyFrame)
})
return(Reduce(rbind,roundResponses))
}
#Find directory for import (be sure to verify that batch #s align from bangData import and imports below):
batches = dir(dataPath, pattern = "^[0-9]+$" )
completeBatches = Filter(function(batch) {
if (any(dir(paste(dataPath,batch,sep="/")) == "batch.json") && (any(dir(paste(dataPath,batch,sep="/")) == "users.json")) ) {
batchData = read_json(paste(dataPath,batch,"batch.json",sep="/"), simplifyVector = TRUE)
return(any(batchData$batchComplete == TRUE))
}
return(FALSE)
}, batches)
userFiles = lapply(completeBatches, function(batch) {
userFile = read_json(paste(dataPath,batch,"users.json",sep="/"), simplifyVector=TRUE)
return(flatten(userFile, recursive = TRUE))
})
Error in flatten(userFile, recursive = TRUE) :
unused argument (recursive = TRUE)
More cleaning before visualizations:
## Apply extract survey function to extract the right columns and rows for viability survey:
survey = 'viabilityCheck'
frame <- extractSurvey(overlappingFiles, survey)
## Reduce to vertically combine rows in roundwithRooms list:
finalRounds = as.data.frame(Reduce(rbind,roundsWithRooms))
## Subset incomplete cases from viability survey dataframe:
## MSB: complete.cases doesn't work when there aren't NAs, but empty lists, alternatives rather than subsetting where
## blacklist is empty? Doens't work: test <- complete.cases(data)
data <- frame[frame$manipulation!="",]
## Rename room to rooms so that both are retained in future merge:
data <- rename(data, rooms = "rooms")
## Subset incomplete cases for final rounds dataframe:
data2 <- finalRounds[finalRounds$results.manipulationCheck!="", ]
## Select only variables of interest from final rounds:
data2 = data2 %>% select(id, batch, room, bonus, name, friends,
friends_history, results.condition, results.format,
results.manipulation,results.manipulationCheck,results.blacklistCheck, round)
## Convert to compatible data types before merge (this should be simplified)
data2$batch <- unlist(data2$batch)
data$batch <- unlist(data$batch)
data2$round <- unlist(data2$round)
data2$id <- unlist(data2$id)
## Before merge, data and data2 should ahve the same # of observations
## Merge columns by id, round and batch #s:
data <- left_join(data, data2, by=NULL)
Joining, by = c("id", "round", "batch")
## Subset only observations with batch #s in complete batches
allConditions <- data[data$batch %in% completeBatches, ]
Conditionally assign conditions based on treatment and results column:
## Messy, but robust? Verify, verify, verify.
data <- data %>% mutate(
condition = case_when(
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='treatment' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='treatment' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='treatment' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='control' & results.format=="c(1, 2, 1)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==2 ~ "B",
results.condition=='control' & results.format=="c(1, 2, 1)" & round==3 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==1 ~ "A",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==2 ~ "Ap",
results.condition=='control' & results.format=="c(1, 1, 2)" & round==3 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==1 ~ "B",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==2 ~ "A",
results.condition=='control' & results.format=="c(2, 1, 1)" & round==3 ~ "Ap" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==1 ~ "A" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==2 ~ "B" ,
results.condition=='baseline' & results.format=="c(1, 2, 3)" & round==3 ~ "C"
))
Set-up for factors for viability questions:
data <- rename(data, "repeatTeam" = results.viabilityCheck.15)
## Remove observations where viability survey wasn't on (remove this line if we want to keep observations with viability off):
data <- na.omit(data)
levels <- c("Strongly Disagree", "Disagree", "Neutral","Agree", "Strongly Agree")
clean <- data %>%
mutate_at(.vars = vars(contains("results.viabilityCheck")), funs(factor(., levels = levels)))
## Viabilitylikert visuals:
## Subset only viabilitySurvey columns and condition column (condition column used to visualize likert responses for conditions)
viabilityLikert <- select(clean, contains("results.viabilityCheck"), "condition", "results.condition")
viabilityLabels = c("1. The members of this team could work for a long time together"
, "2. Most of the members of this team would welcome the opportunity to work as a group again in the future." ,
"3. This team has the capacity for long-term success.",
"4. This team has what it takes to be effective in the future.",
"5. This team would work well together in the future." ,
" 6. This team has positioned itself well for continued success.",
" 7. This team has the ability to perform well in the future. ",
" 8. This team has the ability to function as an ongoing unit." ,
" 9. This team should continue to function as a unit. ",
" 10. This team has the resources to perform well in the future. ",
" 11. This team is well positioned for growth over time. ",
" 12. This team can develop to meet future challenges. ",
" 13. This team has the capacity to sustain itself. ",
" 14. This team has what it takes to endure in future performance episodes.", "condition", "results.condition")
names(viabilityLikert) <- rep(viabilityLabels)
Likert visualizations:
## Likert graph for all viability responses across all conditions (i.e. baseline, control and treatment):
likert.out <- likert(viabilityLikert[-c(15:16)])
plot(likert.out)

## Subset A and Ap (i.e. A prime) responses for treatment group:
# Treatment + A:
treatmentA <- viabilityLikert %>% filter(condition=="A" & results.condition=="treatment")
likert.treatmentA <- likert(treatmentA[-c(15:16)])
plot(likert.treatmentA)

# Treatment + Ap:
treatmentAp <- viabilityLikert %>% filter(condition=="Ap" & results.condition=="treatment")
likert.treatmentAp <- likert(treatmentAp[-c(15:16)])
plot(likert.treatmentAp)

# Treatment + B:
treatmentB <- viabilityLikert %>% filter(condition=="B" & results.condition=="treatment")
likert.treatmentB <- likert(treatmentB[-c(15:16)])
plot(likert.treatmentAp)

## Customize code above to filter on other conditions and treatments of interest.
Exploratory data analysis part #1:
## Create a new dataframe that converts factors to numeric for statistical analyses:
stats <- clean %>% mutate_if(is.factor, as.numeric)
for (i in 1:nrow(stats)) {
stats$sum[i] <- sum(stats[i,1:14])
}
stats$median <- median(stats$sum)
stats$mean <- mean(stats$sum)
## Revalue repeat team: keep plyr b/c some weird R stuff requires library to be called directly (recode values to )
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Yes"="0", "No"="1"))
stats$repeatTeam <- plyr::revalue(stats$repeatTeam, c("Keep this team"="0", "Do not keep this team"="1"))
## Convert to compatible classes for team grouping:
stats$repeatTeam <- as.numeric(stats$repeatTeam)
stats$results.condition <- unlist(stats$results.condition)
stats$results.format <- as.character(stats$results.format)
stats$room <- unlist(stats$room)
## Dplyr to group teams and summarise variables for each group: group_by to find teams and summarise to compact individual results into group level results (i.e. one row of variable results per team)
groupedProportion <- stats %>%
group_by(room, batch, round, condition, results.condition, results.format) %>%
summarise(n=n(), mean=mean(sum), median=median(sum),prop=sum(repeatTeam)/n) %>%
## Filter out all teams with n=1 (i.e. a person in a chat room alone)
filter(n>2)
## Individual proportion:
individualProportion <- stats %>% group_by(round, batch, room) %>%
mutate(sum=sum, mean=mean(sum), median=median(sum), n=n(),prop=sum(repeatTeam)/n) %>% filter(n>1)
## Table showing how many teams we've run in each condition combination:
table(groupedProportion$condition, groupedProportion$results.condition)
control treatment
A 10 12
Ap 10 12
B 7 13
Exploratory data analysis part #2:
## Plot of prop and mean per team with standard error:
ggplot(groupedProportion, aes(x=prop, y=mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") +
labs(subtitle="",
x="Proportion of answers to Q15: ",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.format)

## Unlist for condition for graph:
groupedProportion$results.condition <- unlist(groupedProportion$results.condition)
## Team viability sum and Q15 factor repeat team answers facet_grid by condition, results.condition and results.format (all users)
g <- ggplot(stats, aes(factor(repeatTeam), sum))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Sum of viability measures grouped by team fracture value",
x="Binary fracture value",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.format)

g <- ggplot(stats, aes(factor(repeatTeam), sum))
g + geom_boxplot(varwidth=T, fill="plum") +
labs(subtitle="Individual fracture score vs. mean viability:",
x="",
y="Numeric sum of viability measures questions (range: 7-70)") + facet_grid(condition ~ results.condition)

## groupedProportion: anlaysis on team level
ggplot(groupedProportion, aes(x=prop, y=mean)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(title="Team fracture proportion vs. team mean viability")

## Mean vs. median plot for viability sums per team:
ggplot(groupedProportion, aes(x=mean, y=median)) +
geom_point() +
stat_smooth(method = "lm", col = "red") + labs(main="Scatterplot of median vs. mean for team viability sums")

ggplot(data=groupedProportion, aes(groupedProportion$prop)) +
geom_histogram(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Count of team proportions of fracture value responses",
x="", y="Count") + facet_grid(condition ~ results.format)

Probability of fracture across teams and condition combinations:


Probability of fracture given condition in treatment:
tally(~fractureGreaterEqual50 | condition, data = conditionalPropTreatment, format = "proportion")
condition
fractureGreaterEqual50 A Ap
0 0.5405405 0.6756757
1 0.4594595 0.3243243
Boxplot for fracture scores vs. viability score sum (7-70)

Absolute change in fracture proportions between conditions:
Histogram comparisons of fracture ratios across treatment, control and learning effect conditions
ggplot(data=groupedProportionFractureTreatment, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: treatment condition") + facet_grid(condition ~ results.condition)
Ignoring unknown parameters: breaks

ggplot(data=groupedProportionFractureControl, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: control round") + facet_grid(condition ~ results.condition)
Ignoring unknown parameters: breaks

ggplot(data=groupedProportionFractureLE, aes(fracture)) +
geom_bar(breaks=seq(0, 1, by=0.20),
col="red",
fill="green",
alpha=.2) + labs(title="Fracture ratios: learning effect condition") + facet_grid(results.condition ~ round)
Ignoring unknown parameters: breaks

Graphs for mean distrbution per treatment condition:
## Mean viability distribution graph: treatment condition, A group
barfill <- "#4271AE"
barlines <- "#1F3552"
## Mean for treatment and A group: ##fill-in)
meanDistributionTreatmentA <- ggplot(treatmentAStats, aes(x = sum)) +
geom_histogram(aes(y = ..count..), binwidth = 5,
colour = barlines, fill = barfill) +
scale_x_continuous(name = "Median viability sum",
breaks = seq(0, 100, 20),
limits=c(0, 70)) +
scale_y_continuous(name = "count") +
ggtitle("Frequency of sum of viability scores: N=##fill-in") +
theme_bw() +
theme(axis.line = element_line(size=1, colour = "black"),
panel.grid.major = element_line(colour = "#d3d3d3"),
panel.grid.minor = element_blank(),
panel.border = element_blank(), panel.background = element_blank(),
plot.title = element_text(size = 14, family = "Tahoma", face = "bold"),
text=element_text(family="Tahoma"),
axis.text.x=element_text(colour="black", size = 9),
axis.text.y=element_text(colour="black", size = 9)) +
geom_vline(xintercept = ##fill-in, size = 1, colour = "#FF3721",
linetype = "dashed")
Error: unexpected '=' in:
" geom_vline(xintercept = ##fill-in, size = 1, colour = "#FF3721",
linetype ="
Chat data:
Conditional probabilities:
CHI Squared:
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgU2V0LXVwIHBhY2thZ2VzIC8vIGxpYnJhcmllcyBhbmQgcHJlcGFyZSBmb3IgZGF0YSBpbXBvcnQ6IApgYGB7cn0KIyMgVW5jb21tZW50IGluc3RhbGwucGFja2FnZXMgYW5kIHJ1biBvdXRzaWRlIG9mIG5vdGVib29rIGVudmlyb25tZW50OiAKIyMgaW5zdGFsbC5wYWNrYWdlcyhjKCJwc3ljaCIgLCJ4dGFibGUiLCAidGlkeXZlcnNlIiwgImpzb25saXRlIiwgImxpa2VydCIsICJnZ3Bsb3QyIiwgInBsb3R5IiwgIm1vc2FpYyIpKQoKbGlicmFyeShwc3ljaCkKbGlicmFyeShsaWtlcnQpCmxpYnJhcnkoanNvbmxpdGUpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShtb3NhaWMpCmxpYnJhcnkocGxvdGx5KQpzb3VyY2UoImh0dHA6Ly9wY3d3dy5saXYuYWMudWsvfndpbGxpYW0vUi9jcm9zc3RhYi5yIikKdGhlbWVfc2V0KHRoZW1lX2NsYXNzaWMoKSkKYGBgCgojIyBTZXQtdXAgZGlyZWN0b3JpZXMsIGltcG9ydCBhbmQgY2xlYW4gZGF0YTogCmBgYHtyfQpybShsaXN0PWxzKCkpCnNldHdkKCIvVXNlcnMvYWxsaWVibGFpc2luZy9kZXNrdG9wL2JhbmcvUiIpIApnZXR3ZCgpCmRhdGFQYXRoID0gIi4uLy5kYXRhIgojIyBEZWZpbmUgZnVuY3Rpb24gdG8gZXh0cmFjdCBzdXJ2ZXkgcmVzdWx0czogCmV4dHJhY3RTdXJ2ZXkgPSBmdW5jdGlvbihmcmFtZSxzdXJ2ZXkpIHsKICByb3VuZHMgPSBzZXEoMSxsZW5ndGgoZnJhbWUkcmVzdWx0cy5mb3JtYXRbWzFdXSkpCiAgcm91bmRSZXNwb25zZXMgPSBsYXBwbHkocm91bmRzLCBmdW5jdGlvbihyb3VuZCkgewogICAgZ2V0Q29sID0gcGFzdGUoInJlc3VsdHMuIixzdXJ2ZXksIi4iLHJvdW5kLCBzZXA9IiIpCiAgICBzdXJ2ZXlDb2xzID0gRmlsdGVyKGZ1bmN0aW9uKHgpIGdyZXBsKGdldENvbCx4KSxuYW1lcyhmcmFtZSkpCiAgICBuZXdDb2xzID0gbGFwcGx5KHN1cnZleUNvbHMsIGZ1bmN0aW9uKHgpIGdzdWIoZ2V0Q29sLHBhc3RlKCJyZXN1bHRzLiIsc3VydmV5LCBzZXA9IiIpLHgpICkKICAgIHN1cnZleUZyYW1lID0gZnJhbWVbLHN1cnZleUNvbHNdCiAgICBpZiAoaXMubnVsbChuZXdDb2xzKSkge3JldHVybigiTm8gbmV3Q29scyIpfQogICAgbmFtZXMoc3VydmV5RnJhbWUpID0gbmV3Q29scwogICAgc3VydmV5RnJhbWUkaWQgPSBmcmFtZSRpZAogICAgc3VydmV5RnJhbWUkcm91bmQgPSByb3VuZAogICAgc3VydmV5RnJhbWUkYmF0Y2ggPSBmcmFtZSRiYXRjaAogICAgc3VydmV5RnJhbWUkcm9vbXMgPSBmcmFtZSRyb29tcwogICAgc3VydmV5RnJhbWUkbWFuaXB1bGF0aW9uID0gZnJhbWUkcmVzdWx0cy5tYW5pcHVsYXRpb25DaGVjawogICAgc3VydmV5RnJhbWUkYmxhY2tsaXN0ID0gZnJhbWUkcmVzdWx0cy5ibGFja2xpc3RDaGVjawogICAgcmV0dXJuKHN1cnZleUZyYW1lKQogIH0pCiAgcmV0dXJuKFJlZHVjZShyYmluZCxyb3VuZFJlc3BvbnNlcykpCn0KI0ZpbmQgZGlyZWN0b3J5IGZvciBpbXBvcnQgKGJlIHN1cmUgdG8gdmVyaWZ5IHRoYXQgYmF0Y2ggI3MgYWxpZ24gZnJvbSBiYW5nRGF0YSBpbXBvcnQgYW5kIGltcG9ydHMgYmVsb3cpOiAKYmF0Y2hlcyA9IGRpcihkYXRhUGF0aCwgcGF0dGVybiA9ICJeWzAtOV0rJCIgKQpjb21wbGV0ZUJhdGNoZXMgPSBGaWx0ZXIoZnVuY3Rpb24oYmF0Y2gpIHsgCiAgaWYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJiYXRjaC5qc29uIikgJiYgKGFueShkaXIocGFzdGUoZGF0YVBhdGgsYmF0Y2gsc2VwPSIvIikpID09ICJ1c2Vycy5qc29uIikpICkgewogICAgYmF0Y2hEYXRhID0gcmVhZF9qc29uKHBhc3RlKGRhdGFQYXRoLGJhdGNoLCJiYXRjaC5qc29uIixzZXA9Ii8iKSwgc2ltcGxpZnlWZWN0b3IgPSBUUlVFKQogICAgcmV0dXJuKGFueShiYXRjaERhdGEkYmF0Y2hDb21wbGV0ZSA9PSBUUlVFKSkKICB9IAogIHJldHVybihGQUxTRSkKfSwgYmF0Y2hlcykKdXNlckZpbGVzID0gbGFwcGx5KGNvbXBsZXRlQmF0Y2hlcywgZnVuY3Rpb24oYmF0Y2gpIHsKICB1c2VyRmlsZSA9IHJlYWRfanNvbihwYXN0ZShkYXRhUGF0aCxiYXRjaCwidXNlcnMuanNvbiIsc2VwPSIvIiksIHNpbXBsaWZ5VmVjdG9yPVRSVUUpCiAgcmV0dXJuKGZsYXR0ZW4odXNlckZpbGUsIHJlY3Vyc2l2ZSA9IFRSVUUpKQp9KQoKIyMgUmV0cm9hY3RpdmVseSBmaW5kIHJvb21zIGZyb20gY2hhdCBkYXRhOiAKb3ZlcmxhcHBpbmdGaWxlcyA9IFJlZHVjZShmdW5jdGlvbih4LHkpIG1lcmdlKHgsIHksIGFsbD1UUlVFKSwgdXNlckZpbGVzKQpyb3VuZHNXaXRoUm9vbXMgPSBhcHBseShvdmVybGFwcGluZ0ZpbGVzLDEsZnVuY3Rpb24oeCkgewogIHJvb21zRm9ySW5kaXZpZHVhbCA9IGxhcHBseShzZXEoMSwzKSxmdW5jdGlvbih5KSB7CiAgICB4JHJvb20gPSB4JHJvb21zW3ldCiAgICB4JHJvdW5kID0geQogICAgcmV0dXJuKHgpCiAgfSkKICByZXR1cm4oUmVkdWNlKHJiaW5kLHJvb21zRm9ySW5kaXZpZHVhbCkpCn0pCmxpYnJhcnkodGlkeXZlcnNlKQoKYGBgCgojIyBNb3JlIGNsZWFuaW5nIGJlZm9yZSB2aXN1YWxpemF0aW9uczogCmBgYHtyfQojIyBBcHBseSBleHRyYWN0IHN1cnZleSBmdW5jdGlvbiB0byBleHRyYWN0IHRoZSByaWdodCBjb2x1bW5zIGFuZCByb3dzIGZvciB2aWFiaWxpdHkgc3VydmV5OiAKc3VydmV5ID0gJ3ZpYWJpbGl0eUNoZWNrJwpmcmFtZSA8LSBleHRyYWN0U3VydmV5KG92ZXJsYXBwaW5nRmlsZXMsIHN1cnZleSkKIyMgUmVkdWNlIHRvIHZlcnRpY2FsbHkgY29tYmluZSByb3dzIGluIHJvdW5kd2l0aFJvb21zIGxpc3Q6ICAKZmluYWxSb3VuZHMgPSBhcy5kYXRhLmZyYW1lKFJlZHVjZShyYmluZCxyb3VuZHNXaXRoUm9vbXMpKQojIyBTdWJzZXQgaW5jb21wbGV0ZSBjYXNlcyBmcm9tIHZpYWJpbGl0eSBzdXJ2ZXkgZGF0YWZyYW1lOiAKIyMgTVNCOiBjb21wbGV0ZS5jYXNlcyBkb2Vzbid0IHdvcmsgd2hlbiB0aGVyZSBhcmVuJ3QgTkFzLCBidXQgZW1wdHkgbGlzdHMsIGFsdGVybmF0aXZlcyByYXRoZXIgdGhhbiBzdWJzZXR0aW5nIHdoZXJlIAojIyBibGFja2xpc3QgaXMgZW1wdHk/IERvZW5zJ3Qgd29yazogdGVzdCA8LSBjb21wbGV0ZS5jYXNlcyhkYXRhKQpkYXRhIDwtIGZyYW1lW2ZyYW1lJG1hbmlwdWxhdGlvbiE9IiIsXQojIyBSZW5hbWUgcm9vbSB0byByb29tcyBzbyB0aGF0IGJvdGggYXJlIHJldGFpbmVkIGluIGZ1dHVyZSBtZXJnZTogCmRhdGEgPC0gcmVuYW1lKGRhdGEsIHJvb21zID0gInJvb21zIikKIyMgU3Vic2V0IGluY29tcGxldGUgY2FzZXMgZm9yIGZpbmFsIHJvdW5kcyBkYXRhZnJhbWU6IApkYXRhMiA8LSBmaW5hbFJvdW5kc1tmaW5hbFJvdW5kcyRyZXN1bHRzLm1hbmlwdWxhdGlvbkNoZWNrIT0iIiwgXQojIyBTZWxlY3Qgb25seSB2YXJpYWJsZXMgb2YgaW50ZXJlc3QgZnJvbSBmaW5hbCByb3VuZHM6IApkYXRhMiA9IGRhdGEyICU+JSBzZWxlY3QoaWQsIGJhdGNoLCByb29tLCBib251cywgbmFtZSwgZnJpZW5kcywgCiAgICAgICAgICAgICAgICAgICAgICAgICBmcmllbmRzX2hpc3RvcnksIHJlc3VsdHMuY29uZGl0aW9uLCByZXN1bHRzLmZvcm1hdCwKICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMubWFuaXB1bGF0aW9uLHJlc3VsdHMubWFuaXB1bGF0aW9uQ2hlY2sscmVzdWx0cy5ibGFja2xpc3RDaGVjaywgcm91bmQpCiMjIENvbnZlcnQgdG8gY29tcGF0aWJsZSBkYXRhIHR5cGVzIGJlZm9yZSBtZXJnZSAodGhpcyBzaG91bGQgYmUgc2ltcGxpZmllZCkKZGF0YTIkYmF0Y2ggPC0gdW5saXN0KGRhdGEyJGJhdGNoKQpkYXRhJGJhdGNoIDwtIHVubGlzdChkYXRhJGJhdGNoKQpkYXRhMiRyb3VuZCA8LSB1bmxpc3QoZGF0YTIkcm91bmQpCmRhdGEyJGlkIDwtIHVubGlzdChkYXRhMiRpZCkKIyMgQmVmb3JlIG1lcmdlLCBkYXRhIGFuZCBkYXRhMiBzaG91bGQgYWh2ZSB0aGUgc2FtZSAjIG9mIG9ic2VydmF0aW9ucwojIyBNZXJnZSBjb2x1bW5zIGJ5IGlkLCByb3VuZCBhbmQgYmF0Y2ggI3M6IApkYXRhIDwtIGxlZnRfam9pbihkYXRhLCBkYXRhMiwgYnk9TlVMTCkKIyMgU3Vic2V0IG9ubHkgb2JzZXJ2YXRpb25zIHdpdGggYmF0Y2ggI3MgaW4gY29tcGxldGUgYmF0Y2hlcyAKYWxsQ29uZGl0aW9ucyA8LSBkYXRhW2RhdGEkYmF0Y2ggJWluJSBjb21wbGV0ZUJhdGNoZXMsIF0KYGBgCiMjIENvbmRpdGlvbmFsbHkgYXNzaWduIGNvbmRpdGlvbnMgYmFzZWQgb24gdHJlYXRtZW50IGFuZCByZXN1bHRzIGNvbHVtbjogCmBgYHtyfQojIyBNZXNzeSwgYnV0IHJvYnVzdD8gVmVyaWZ5LCB2ZXJpZnksIHZlcmlmeS4gIApkYXRhIDwtIGRhdGEgJT4lIG11dGF0ZSgKICBjb25kaXRpb24gPSBjYXNlX3doZW4oCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTEgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0yIH4gIkIiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MyB+ICJBcCIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0xIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAxLCAyKSIgJiByb3VuZD09MiB+ICJBcCIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0zIH4gIkIiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0ndHJlYXRtZW50JyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MSB+ICJCIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J3RyZWF0bWVudCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTIgfiAiQSIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSd0cmVhdG1lbnQnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiAsCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDIsIDEpIiAmIHJvdW5kPT0xIH4gIkEiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMSkiICYgcm91bmQ9PTIgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAyLCAxKSIgJiByb3VuZD09MyB+ICJBcCIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygxLCAxLCAyKSIgJiByb3VuZD09MSB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0yIH4gIkFwIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDEsIDEsIDIpIiAmIHJvdW5kPT0zIH4gIkIiLCAKICAgIHJlc3VsdHMuY29uZGl0aW9uPT0nY29udHJvbCcgJiByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PTEgfiAiQiIsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdjb250cm9sJyAmIHJlc3VsdHMuZm9ybWF0PT0iYygyLCAxLCAxKSIgJiByb3VuZD09MiB+ICJBIiwgCiAgICByZXN1bHRzLmNvbmRpdGlvbj09J2NvbnRyb2wnICYgcmVzdWx0cy5mb3JtYXQ9PSJjKDIsIDEsIDEpIiAmIHJvdW5kPT0zIH4gIkFwIiAsIAogICAgcmVzdWx0cy5jb25kaXRpb249PSdiYXNlbGluZScgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMykiICYgcm91bmQ9PTEgfiAiQSIgLAogICAgcmVzdWx0cy5jb25kaXRpb249PSdiYXNlbGluZScgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMykiICYgcm91bmQ9PTIgfiAiQiIgLAogICAgcmVzdWx0cy5jb25kaXRpb249PSdiYXNlbGluZScgJiByZXN1bHRzLmZvcm1hdD09ImMoMSwgMiwgMykiICYgcm91bmQ9PTMgfiAiQyIgCiAgKSkgCmBgYAoKIyMgU2V0LXVwIGZvciBmYWN0b3JzIGZvciB2aWFiaWxpdHkgcXVlc3Rpb25zOiAKYGBge3J9CmRhdGEgPC0gcmVuYW1lKGRhdGEsICJyZXBlYXRUZWFtIiA9IHJlc3VsdHMudmlhYmlsaXR5Q2hlY2suMTUpCiMjIFJlbW92ZSBvYnNlcnZhdGlvbnMgd2hlcmUgdmlhYmlsaXR5IHN1cnZleSB3YXNuJ3Qgb24gKHJlbW92ZSB0aGlzIGxpbmUgaWYgd2Ugd2FudCB0byBrZWVwIG9ic2VydmF0aW9ucyB3aXRoIHZpYWJpbGl0eSBvZmYpOiAKZGF0YSA8LSBuYS5vbWl0KGRhdGEpCmxldmVscyA8LSBjKCJTdHJvbmdseSBEaXNhZ3JlZSIsICJEaXNhZ3JlZSIsICJOZXV0cmFsIiwiQWdyZWUiLCAiU3Ryb25nbHkgQWdyZWUiKSAKY2xlYW4gPC0gZGF0YSAlPiUgCiAgbXV0YXRlX2F0KC52YXJzID0gdmFycyhjb250YWlucygicmVzdWx0cy52aWFiaWxpdHlDaGVjayIpKSwgZnVucyhmYWN0b3IoLiwgbGV2ZWxzID0gbGV2ZWxzKSkpIAojIyBWaWFiaWxpdHlsaWtlcnQgdmlzdWFsczogCiMjIFN1YnNldCBvbmx5IHZpYWJpbGl0eVN1cnZleSBjb2x1bW5zIGFuZCBjb25kaXRpb24gY29sdW1uIChjb25kaXRpb24gY29sdW1uIHVzZWQgdG8gdmlzdWFsaXplIGxpa2VydCByZXNwb25zZXMgZm9yIGNvbmRpdGlvbnMpCnZpYWJpbGl0eUxpa2VydCA8LSBzZWxlY3QoY2xlYW4sIGNvbnRhaW5zKCJyZXN1bHRzLnZpYWJpbGl0eUNoZWNrIiksICJjb25kaXRpb24iLCAicmVzdWx0cy5jb25kaXRpb24iKQp2aWFiaWxpdHlMYWJlbHMgPSBjKCIxLiBUaGUgbWVtYmVycyBvZiB0aGlzIHRlYW0gY291bGQgd29yayBmb3IgYSBsb25nIHRpbWUgdG9nZXRoZXIiIAogICAgICAgICAgICAgICAgICAgICwgIjIuIE1vc3Qgb2YgdGhlIG1lbWJlcnMgb2YgdGhpcyB0ZWFtIHdvdWxkIHdlbGNvbWUgdGhlIG9wcG9ydHVuaXR5IHRvIHdvcmsgYXMgYSBncm91cCBhZ2FpbiBpbiB0aGUgZnV0dXJlLiIgLCAKICAgICAgICAgICAgICAgICAgICAiMy4gVGhpcyB0ZWFtIGhhcyB0aGUgY2FwYWNpdHkgZm9yIGxvbmctdGVybSBzdWNjZXNzLiIsIAogICAgICAgICAgICAgICAgICAgICI0LiBUaGlzIHRlYW0gaGFzIHdoYXQgaXQgdGFrZXMgdG8gYmUgZWZmZWN0aXZlIGluIHRoZSBmdXR1cmUuIiwgCiAgICAgICAgICAgICAgICAgICAgIjUuIFRoaXMgdGVhbSB3b3VsZCB3b3JrIHdlbGwgdG9nZXRoZXIgaW4gdGhlIGZ1dHVyZS4iICwgCiAgICAgICAgICAgICAgICAgICAgIiA2LiBUaGlzIHRlYW0gaGFzIHBvc2l0aW9uZWQgaXRzZWxmIHdlbGwgZm9yIGNvbnRpbnVlZCBzdWNjZXNzLiIsICAKICAgICAgICAgICAgICAgICAgICAiIDcuIFRoaXMgdGVhbSBoYXMgdGhlIGFiaWxpdHkgdG8gcGVyZm9ybSB3ZWxsIGluIHRoZSBmdXR1cmUuICIsIAogICAgICAgICAgICAgICAgICAgICIgOC4gVGhpcyB0ZWFtIGhhcyB0aGUgYWJpbGl0eSB0byBmdW5jdGlvbiBhcyBhbiBvbmdvaW5nIHVuaXQuIiAsIAogICAgICAgICAgICAgICAgICAgICIgOS4gVGhpcyB0ZWFtIHNob3VsZCBjb250aW51ZSB0byBmdW5jdGlvbiBhcyBhIHVuaXQuICIsIAogICAgICAgICAgICAgICAgICAgICIgMTAuIFRoaXMgdGVhbSBoYXMgdGhlIHJlc291cmNlcyB0byBwZXJmb3JtIHdlbGwgaW4gdGhlIGZ1dHVyZS4gIiwgCiAgICAgICAgICAgICAgICAgICAgIiAxMS4gVGhpcyB0ZWFtIGlzIHdlbGwgcG9zaXRpb25lZCBmb3IgZ3Jvd3RoIG92ZXIgdGltZS4gIiwgCiAgICAgICAgICAgICAgICAgICAgIiAxMi4gVGhpcyB0ZWFtIGNhbiBkZXZlbG9wIHRvIG1lZXQgZnV0dXJlIGNoYWxsZW5nZXMuICIsIAogICAgICAgICAgICAgICAgICAgICIgMTMuIFRoaXMgdGVhbSBoYXMgdGhlIGNhcGFjaXR5IHRvIHN1c3RhaW4gaXRzZWxmLiAiLCAKICAgICAgICAgICAgICAgICAgICAiIDE0LiBUaGlzIHRlYW0gaGFzIHdoYXQgaXQgdGFrZXMgdG8gZW5kdXJlIGluIGZ1dHVyZSBwZXJmb3JtYW5jZSBlcGlzb2Rlcy4iLCAiY29uZGl0aW9uIiwgInJlc3VsdHMuY29uZGl0aW9uIikgCm5hbWVzKHZpYWJpbGl0eUxpa2VydCkgPC0gcmVwKHZpYWJpbGl0eUxhYmVscykgCmBgYAoKIyMgTGlrZXJ0IHZpc3VhbGl6YXRpb25zOiAKYGBge3J9CiMjIExpa2VydCBncmFwaCBmb3IgYWxsIHZpYWJpbGl0eSByZXNwb25zZXMgYWNyb3NzIGFsbCBjb25kaXRpb25zIChpLmUuIGJhc2VsaW5lLCBjb250cm9sIGFuZCB0cmVhdG1lbnQpOiAKbGlrZXJ0Lm91dCA8LSBsaWtlcnQodmlhYmlsaXR5TGlrZXJ0Wy1jKDE1OjE2KV0pIApwbG90KGxpa2VydC5vdXQpCiMjIFN1YnNldCBBIGFuZCBBcCAoaS5lLiBBIHByaW1lKSByZXNwb25zZXMgZm9yIHRyZWF0bWVudCBncm91cDogCiMgVHJlYXRtZW50ICsgQTogCnRyZWF0bWVudEEgPC0gdmlhYmlsaXR5TGlrZXJ0ICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIgJiByZXN1bHRzLmNvbmRpdGlvbj09InRyZWF0bWVudCIpIApsaWtlcnQudHJlYXRtZW50QSA8LSBsaWtlcnQodHJlYXRtZW50QVstYygxNToxNildKQpwbG90KGxpa2VydC50cmVhdG1lbnRBKQojIFRyZWF0bWVudCArIEFwOiAKdHJlYXRtZW50QXAgPC0gdmlhYmlsaXR5TGlrZXJ0ICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQXAiICYgcmVzdWx0cy5jb25kaXRpb249PSJ0cmVhdG1lbnQiKSAKbGlrZXJ0LnRyZWF0bWVudEFwIDwtIGxpa2VydCh0cmVhdG1lbnRBcFstYygxNToxNildKQpwbG90KGxpa2VydC50cmVhdG1lbnRBcCkKIyBUcmVhdG1lbnQgKyBCOiAKdHJlYXRtZW50QiA8LSB2aWFiaWxpdHlMaWtlcnQgJT4lIGZpbHRlcihjb25kaXRpb249PSJCIiAmIHJlc3VsdHMuY29uZGl0aW9uPT0idHJlYXRtZW50IikgCmxpa2VydC50cmVhdG1lbnRCIDwtIGxpa2VydCh0cmVhdG1lbnRCWy1jKDE1OjE2KV0pCnBsb3QobGlrZXJ0LnRyZWF0bWVudEFwKQojIyBDdXN0b21pemUgY29kZSBhYm92ZSB0byBmaWx0ZXIgb24gb3RoZXIgY29uZGl0aW9ucyBhbmQgdHJlYXRtZW50cyBvZiBpbnRlcmVzdC4gCmBgYAoKIyMgRXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyBwYXJ0ICMxOiAKYGBge3J9CiMjIENyZWF0ZSBhIG5ldyBkYXRhZnJhbWUgdGhhdCBjb252ZXJ0cyBmYWN0b3JzIHRvIG51bWVyaWMgZm9yIHN0YXRpc3RpY2FsIGFuYWx5c2VzOiAKc3RhdHMgPC0gY2xlYW4gJT4lIG11dGF0ZV9pZihpcy5mYWN0b3IsIGFzLm51bWVyaWMpCmZvciAoaSBpbiAxOm5yb3coc3RhdHMpKSB7CiAgc3RhdHMkc3VtW2ldIDwtIHN1bShzdGF0c1tpLDE6MTRdKSAgICAgICAgICAgICAgICAgICAgICAgICAgCn0gCnN0YXRzJG1lZGlhbiA8LSBtZWRpYW4oc3RhdHMkc3VtKQpzdGF0cyRtZWFuIDwtIG1lYW4oc3RhdHMkc3VtKQojIyBSZXZhbHVlIHJlcGVhdCB0ZWFtOiBrZWVwIHBseXIgYi9jIHNvbWUgd2VpcmQgUiBzdHVmZiByZXF1aXJlcyBsaWJyYXJ5IHRvIGJlIGNhbGxlZCBkaXJlY3RseSAocmVjb2RlIHZhbHVlcyB0byApCnN0YXRzJHJlcGVhdFRlYW0gPC0gcGx5cjo6cmV2YWx1ZShzdGF0cyRyZXBlYXRUZWFtLCBjKCJZZXMiPSIwIiwgIk5vIj0iMSIpKQpzdGF0cyRyZXBlYXRUZWFtIDwtIHBseXI6OnJldmFsdWUoc3RhdHMkcmVwZWF0VGVhbSwgYygiS2VlcCB0aGlzIHRlYW0iPSIwIiwgIkRvIG5vdCBrZWVwIHRoaXMgdGVhbSI9IjEiKSkKIyMgQ29udmVydCB0byBjb21wYXRpYmxlIGNsYXNzZXMgZm9yIHRlYW0gZ3JvdXBpbmc6IApzdGF0cyRyZXBlYXRUZWFtIDwtIGFzLm51bWVyaWMoc3RhdHMkcmVwZWF0VGVhbSkKc3RhdHMkcmVzdWx0cy5jb25kaXRpb24gPC0gdW5saXN0KHN0YXRzJHJlc3VsdHMuY29uZGl0aW9uKQpzdGF0cyRyZXN1bHRzLmZvcm1hdCA8LSBhcy5jaGFyYWN0ZXIoc3RhdHMkcmVzdWx0cy5mb3JtYXQpCnN0YXRzJHJvb20gPC0gdW5saXN0KHN0YXRzJHJvb20pCiMjIERwbHlyIHRvIGdyb3VwIHRlYW1zIGFuZCBzdW1tYXJpc2UgdmFyaWFibGVzIGZvciBlYWNoIGdyb3VwOiBncm91cF9ieSB0byBmaW5kIHRlYW1zIGFuZCBzdW1tYXJpc2UgdG8gY29tcGFjdCBpbmRpdmlkdWFsIHJlc3VsdHMgaW50byBncm91cCBsZXZlbCByZXN1bHRzIChpLmUuIG9uZSByb3cgb2YgdmFyaWFibGUgcmVzdWx0cyBwZXIgdGVhbSkKZ3JvdXBlZFByb3BvcnRpb24gPC0gc3RhdHMgJT4lCiAgZ3JvdXBfYnkocm9vbSwgYmF0Y2gsIHJvdW5kLCBjb25kaXRpb24sIHJlc3VsdHMuY29uZGl0aW9uLCByZXN1bHRzLmZvcm1hdCkgJT4lIAogIHN1bW1hcmlzZShuPW4oKSwgbWVhbj1tZWFuKHN1bSksIG1lZGlhbj1tZWRpYW4oc3VtKSxwcm9wPXN1bShyZXBlYXRUZWFtKS9uKSAlPiUgCiMjIEZpbHRlciBvdXQgYWxsIHRlYW1zIHdpdGggbj0xIChpLmUuIGEgcGVyc29uIGluIGEgY2hhdCByb29tIGFsb25lKQogIGZpbHRlcihuPjIpCiMjIEluZGl2aWR1YWwgcHJvcG9ydGlvbjogCmluZGl2aWR1YWxQcm9wb3J0aW9uIDwtIHN0YXRzICU+JSBncm91cF9ieShyb3VuZCwgYmF0Y2gsIHJvb20pICU+JSAKICBtdXRhdGUoc3VtPXN1bSwgbWVhbj1tZWFuKHN1bSksIG1lZGlhbj1tZWRpYW4oc3VtKSwgbj1uKCkscHJvcD1zdW0ocmVwZWF0VGVhbSkvbikgJT4lIGZpbHRlcihuPjEpCgojIyBUYWJsZSBzaG93aW5nIGhvdyBtYW55IHRlYW1zIHdlJ3ZlIHJ1biBpbiBlYWNoIGNvbmRpdGlvbiBjb21iaW5hdGlvbjogIAp0YWJsZShncm91cGVkUHJvcG9ydGlvbiRjb25kaXRpb24sIGdyb3VwZWRQcm9wb3J0aW9uJHJlc3VsdHMuY29uZGl0aW9uKQpgYGAKCiMjIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgcGFydCAjMjogCmBgYHtyfQojIyBQbG90IG9mIHByb3AgYW5kIG1lYW4gcGVyIHRlYW0gd2l0aCBzdGFuZGFyZCBlcnJvcjogCmdncGxvdChncm91cGVkUHJvcG9ydGlvbiwgYWVzKHg9cHJvcCwgeT1tZWFuKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJyZWQiKSArIAogIGxhYnMoc3VidGl0bGU9IiIsIAogICAgICAgeD0iUHJvcG9ydGlvbiBvZiBhbnN3ZXJzIHRvIFExNTogIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmZvcm1hdCkKCiMjIFVubGlzdCBmb3IgY29uZGl0aW9uIGZvciBncmFwaDogCmdyb3VwZWRQcm9wb3J0aW9uJHJlc3VsdHMuY29uZGl0aW9uIDwtIHVubGlzdChncm91cGVkUHJvcG9ydGlvbiRyZXN1bHRzLmNvbmRpdGlvbikKIyMgVGVhbSB2aWFiaWxpdHkgc3VtIGFuZCBRMTUgZmFjdG9yIHJlcGVhdCB0ZWFtIGFuc3dlcnMgZmFjZXRfZ3JpZCBieSBjb25kaXRpb24sIHJlc3VsdHMuY29uZGl0aW9uIGFuZCByZXN1bHRzLmZvcm1hdCAoYWxsIHVzZXJzKSAKZyA8LSBnZ3Bsb3Qoc3RhdHMsIGFlcyhmYWN0b3IocmVwZWF0VGVhbSksIHN1bSkpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iU3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBncm91cGVkIGJ5IHRlYW0gZnJhY3R1cmUgdmFsdWUiLCAKICAgICAgIHg9IkJpbmFyeSBmcmFjdHVyZSB2YWx1ZSIsCiAgICAgICB5PSJOdW1lcmljIHN1bSBvZiB2aWFiaWxpdHkgbWVhc3VyZXMgcXVlc3Rpb25zIChyYW5nZTogNy03MCkiKSArIGZhY2V0X2dyaWQoY29uZGl0aW9uIH4gcmVzdWx0cy5mb3JtYXQpCgpnIDwtIGdncGxvdChzdGF0cywgYWVzKGZhY3RvcihyZXBlYXRUZWFtKSwgc3VtKSkKZyArIGdlb21fYm94cGxvdCh2YXJ3aWR0aD1ULCBmaWxsPSJwbHVtIikgKyAKICBsYWJzKHN1YnRpdGxlPSJJbmRpdmlkdWFsIGZyYWN0dXJlIHNjb3JlIHZzLiBtZWFuIHZpYWJpbGl0eToiLCAKICAgICAgIHg9IiIsCiAgICAgICB5PSJOdW1lcmljIHN1bSBvZiB2aWFiaWxpdHkgbWVhc3VyZXMgcXVlc3Rpb25zIChyYW5nZTogNy03MCkiKSArIGZhY2V0X2dyaWQoY29uZGl0aW9uIH4gcmVzdWx0cy5jb25kaXRpb24pCgojIyBncm91cGVkUHJvcG9ydGlvbjogYW5sYXlzaXMgb24gdGVhbSBsZXZlbCAKCmdncGxvdChncm91cGVkUHJvcG9ydGlvbiwgYWVzKHg9cHJvcCwgeT1tZWFuKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbCA9ICJyZWQiKSArIGxhYnModGl0bGU9IlRlYW0gZnJhY3R1cmUgcHJvcG9ydGlvbiB2cy4gdGVhbSBtZWFuIHZpYWJpbGl0eSIpIAoKIyMgTWVhbiB2cy4gbWVkaWFuIHBsb3QgZm9yIHZpYWJpbGl0eSBzdW1zIHBlciB0ZWFtOiAKZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uLCBhZXMoeD1tZWFuLCB5PW1lZGlhbikpICsgCiAgZ2VvbV9wb2ludCgpICsKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iLCBjb2wgPSAicmVkIikgKyBsYWJzKG1haW49IlNjYXR0ZXJwbG90IG9mIG1lZGlhbiB2cy4gbWVhbiBmb3IgdGVhbSB2aWFiaWxpdHkgc3VtcyIpCgpnZ3Bsb3QoZGF0YT1ncm91cGVkUHJvcG9ydGlvbiwgYWVzKGdyb3VwZWRQcm9wb3J0aW9uJHByb3ApKSArIAogIGdlb21faGlzdG9ncmFtKGJyZWFrcz1zZXEoMCwgMSwgYnk9MC4yMCksIAogICAgICAgICAgICAgICAgIGNvbD0icmVkIiwgCiAgICAgICAgICAgICAgICAgZmlsbD0iZ3JlZW4iLCAKICAgICAgICAgICAgICAgICBhbHBoYT0uMikgKyBsYWJzKHRpdGxlPSJDb3VudCBvZiB0ZWFtIHByb3BvcnRpb25zIG9mIGZyYWN0dXJlIHZhbHVlIHJlc3BvbnNlcyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0iIiwgeT0iQ291bnQiKSArIGZhY2V0X2dyaWQoY29uZGl0aW9uIH4gcmVzdWx0cy5mb3JtYXQpCgpgYGAKCiMjIFByb2JhYmlsaXR5IG9mIGZyYWN0dXJlIGFjcm9zcyB0ZWFtcyBhbmQgY29uZGl0aW9uIGNvbWJpbmF0aW9uczogCmBgYHtyfQojIyBEZWZpbmUgYW5kIGluaXRpYWxpemUgY3V0LW9mZiBwb2ludCBmb3IgZnJhY3R1cmU6IApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlIDwtIGdyb3VwZWRQcm9wb3J0aW9uICU+JQogIGdyb3VwX2J5KHJlc3VsdHMuY29uZGl0aW9uLCBjb25kaXRpb24pICU+JSAKICBtdXRhdGUoZnJhY3R1cmVHcmVhdGVyNTAgPSBjYXNlX3doZW4gKHByb3A8PS41MCB+ICIwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcD4uNTB+ICIxIiksIAogICAgICAgICBmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwID0gY2FzZV93aGVuIChwcm9wPC41MCB+ICIwIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcD49LjUwIH4gIjEiKSkKCiMjIEZyYWN0dXJlIHByb3BvcnRpb24gc2NhdHRlcnBsb3RzOiAKIyMgTGVhcm5pbmcgZWZmZWN0IC8vIGJhc2VsaW5lOiAKIyMgTWFrZSBuZXcgZGF0YSB0aGF0IGluY2x1ZGVzIHRlYW1zIHdpdGggZGlmZmVyZW50IHJvdW5kIDEgYW5kIHJvdW5kIDMgdGVhbXM6IApncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlTEUgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSAlPiUgZmlsdGVyKHJlc3VsdHMuZm9ybWF0PT0iYygxLCAxLCAyKSIgfCByZXN1bHRzLmZvcm1hdD09ImMoMiwgMSwgMSkiICYgcm91bmQ9PSIxIiB8IHJvdW5kPT0iMyIpIApmcmFjdHVyZUxFMSA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlTEUgJT4lIGZpbHRlcihyb3VuZD09IjEiKQpmcmFjdHVyZUxFMiA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlTEUgJT4lIGZpbHRlcihyb3VuZD09IjMiKQoKIyMgVHJlYXRtZW50OiAKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlICU+JSAKZmlsdGVyKHJlc3VsdHMuY29uZGl0aW9uPT0idHJlYXRtZW50IikKdHJlYXRtZW50RnJhY3R1cmUxIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVUcmVhdG1lbnQgJT4lIGZpbHRlcihjb25kaXRpb249PSJBIikKdHJlYXRtZW50RnJhY3R1cmUyIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVUcmVhdG1lbnQgJT4lIGZpbHRlcihjb25kaXRpb249PSJBcCIpCnRyZWF0bWVudEZyYWN0dXJlIDwtIGNiaW5kKHRyZWF0bWVudEZyYWN0dXJlMSwgdHJlYXRtZW50RnJhY3R1cmUyKQoKZ2dwbG90KHRyZWF0bWVudEZyYWN0dXJlLCBhZXMocHJvcCwgcHJvcDEpKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX2ppdHRlcigpICsgY29vcmRfZml4ZWQoKSArIHhsaW0oMC4wLDEuMCkgKyB5bGltKDAuMCwxLjApICsgbGFicyh0aXRsZT0iUHJvcG9ydGlvbiBvZiB0ZWFtIGZyYWN0dXJlIGluIHRoZSBmaXJzdCB2cy4gdGhpcmQgaW4gdHJlYXRtZW50Iiwgc3VidGl0bGU9Ik5vIGZyYWN0dXJlPTAsIEZyYWN0dXJlPTEiLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeD0iRnJhY3R1cmUgdGhlIGZpcnN0IHRpbWUgYSB0ZWFtIGludGVyYWN0cyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9IkZyYWN0dXJlIHRoZSBzZWNvbmQgdGltZSBhIHRlYW0gaW50ZXJhY3RzLCB3aXRob3V0IGtub3dpbmcgaXQiKSAKCiMjIENvbnRyb2w6ICAKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUNvbnRyb2wgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSAlPiUgCiAgZmlsdGVyKHJlc3VsdHMuY29uZGl0aW9uPT0iY29udHJvbCIpIApjb250cm9sRnJhY3R1cmUxIDwtIGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVDb250cm9sICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIpCmNvbnRyb2xGcmFjdHVyZTIgPC0gZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUNvbnRyb2wgJT4lIGZpbHRlcihjb25kaXRpb249PSJBcCIpCmNvbnRyb2xGcmFjdHVyZSA8LSBjYmluZChjb250cm9sRnJhY3R1cmUxLCBjb250cm9sRnJhY3R1cmUyKQoKZ2dwbG90KGNvbnRyb2xGcmFjdHVyZSwgYWVzKHByb3AsIHByb3AxKSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9qaXR0ZXIoKSArIGNvb3JkX2ZpeGVkKCkgKyB4bGltKDAuMCwxLjApICsgeWxpbSgwLjAsMS4wKSArIGxhYnModGl0bGU9IlByb3BvcnRpb24gb2YgdGVhbSBmcmFjdHVyZSBpbiB0aGUgZmlyc3QgdnMuIHRoaXJkIGluIGNvbnRyb2wiLCBzdWJ0aXRsZT0iTm8gZnJhY3R1cmU9MCwgRnJhY3R1cmU9MSIsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4PSJGcmFjdHVyZSB0aGUgZmlyc3QgdGltZSBhIHRlYW0gaW50ZXJhY3RzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeT0iRnJhY3R1cmUgdGhlIHNlY29uZCB0aW1lIGEgdGVhbSBpbnRlcmFjdHMsIHdpdGhvdXQga25vd2luZyBpdCIpIAoKCmcgPC0gZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUsIGFlcyhmYWN0b3IoZnJhY3R1cmVHcmVhdGVyNTApLCBtZWFuKSkKZyArIGdlb21fYm94cGxvdCh2YXJ3aWR0aD1ULCBmaWxsPSJwbHVtIikgKyAKICBsYWJzKHN1YnRpdGxlPSJUZWFtIGZyYWN0dXJlIHZhbHVlIHZzLiBtZWFuIHZpYWJpbGl0eSBzY29yZTogZnJhY3R1cmUgPjAuNTAiLCAKICAgICAgIHg9IiIsCiAgICAgICB5PSJOdW1lcmljIHN1bSBvZiB2aWFiaWxpdHkgbWVhc3VyZXMgcXVlc3Rpb25zIChyYW5nZTogNy03MCkiKSAKCmcgPC0gZ2dwbG90KGdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmUsIGFlcyhmYWN0b3IoZnJhY3R1cmVHcmVhdGVyRXF1YWw1MCksIG1lYW4pKSAKZyArIGdlb21fYm94cGxvdCh2YXJ3aWR0aD1ULCBmaWxsPSJwbHVtIikgKyAKICBsYWJzKHN1YnRpdGxlPSJUZWFtIGZyYWN0dXJlIHZhbHVlIHZzLiBtZWFuIHZpYWJpbGl0eSBzY29yZTogZnJhY3R1cmUgPj0wLjUwIiwgCiAgICAgICB4PSIiLAogICAgICAgeT0iTnVtZXJpYyBzdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIHF1ZXN0aW9ucyAocmFuZ2U6IDctNzApIikgCgpnIDwtIGdncGxvdChncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50LCBhZXMoZmFjdG9yKGZyYWN0dXJlKSwgbWVhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBmcmFjdHVyZSB2YWx1ZSB2cy4gbWVhbiB2aWFiaWxpdHkgc2NvcmU6IGZyYWN0dXJlID4wLjUwIiwgCiAgICAgICB4PSIiLAogICAgICAgeT0iTnVtZXJpYyBzdW0gb2YgdmlhYmlsaXR5IG1lYXN1cmVzIHF1ZXN0aW9ucyAocmFuZ2U6IDctNzApIikgCgoKIyMgRGVmaW5pbmcgZnJhY3R1cmU6IAoKIyMgVFJFQVRNRU5UIEVGRkVDVDogCiMgIyMgT3ZlcmFsbCBmcmFjdHVyZSBjaGFuZ2U6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT10cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmUsMCwxKSkgCiMgIyMgTm8gZnJhY3R1cmUgdG8gZnJhY3R1cmU6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0wICYgdHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlPT0xLDEsMCkpCiMgIyMgRnJhY3R1cmUgdG8gbm8gZnJhY3R1cmU6IAojIHN1bShpZmVsc2UodHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlPT0xICYgdHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlPT0wLDEsMCkpCiMgIyMgQ09OVFJPTCBFRkZFQ1Q6IAojICMjIE92ZXJhbGwgZnJhY3R1cmUgY2hhbmdlOiAKIyBzdW0oaWZlbHNlKGNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmU9PWNvbnRyb2xGcmFjdHVyZTIkZnJhY3R1cmUsMCwxKSkKIyAjIyBObyBmcmFjdHVyZSB0byBmcmFjdHVyZTogCiMgc3VtKGlmZWxzZShjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlPT0wICYgY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZT09MSwxLDApKQojICMjIEZyYWN0dXJlIHRvIG5vIGZyYWN0dXJlOiAKIyBzdW0oaWZlbHNlKGNvbnRyb2xGcmFjdHVyZTEkZnJhY3R1cmU9PTEgJiBjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlPT0wLDEsMCkpCiMgIyMgTEVBUk5JTkcgRUZGRUNUIAojICMjIE92ZXJhbGwgZnJhY3R1cmUgY2hhbmdlOiAKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT1mcmFjdHVyZUxFMiRmcmFjdHVyZSwwLDEpKSAKIyAjIyBObyBmcmFjdHVyZSB0byBmcmFjdHVyZToKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT0wICYgZnJhY3R1cmVMRTIkZnJhY3R1cmU9PTEsMSwwKSkKIyAjIyBGcmFjdHVyZSB0byBubyBmcmFjdHVyZSAKIyBzdW0oaWZlbHNlKGZyYWN0dXJlTEUxJGZyYWN0dXJlPT0xICYgZnJhY3R1cmVMRTIkZnJhY3R1cmU9PTAsMSwwKSkKYGBgCgojIyAKCgojIyBQcm9iYWJpbGl0eSBvZiBmcmFjdHVyZSBnaXZlbiBjb25kaXRpb24gaW4gdHJlYXRtZW50OiAKYGBge3J9CmNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCA8LSBncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlVHJlYXRtZW50ICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIgfCBjb25kaXRpb249PSJBcCIpCiMjIEdyZWF0ZXIgdGhhbiA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXI1MCB8IGNvbmRpdGlvbiwgZGF0YSA9IGNvbmRpdGlvbmFsUHJvYlRyZWF0bWVudCwgZm9ybWF0ID0gInByb3BvcnRpb24iKQojIyBHcmVhdGVyIG9yIGVxdWFsIDUwOiAKdGFsbHkofmZyYWN0dXJlR3JlYXRlckVxdWFsNTAgfCBjb25kaXRpb24sIGRhdGEgPSBjb25kaXRpb25hbFByb2JUcmVhdG1lbnQsIGZvcm1hdCA9ICJwcm9wb3J0aW9uIikKCmNvbmRpdGlvbmFsUHJvYkNvbnRyb2wgPC0gZ3JvdXBlZFByb3BvcnRpb25Db250cm9sICU+JSBmaWx0ZXIoY29uZGl0aW9uPT0iQSIgfCBjb25kaXRpb249PSJBcCIpCiMjIEdyZWF0ZXIgdGhhbiA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXI1MCB8IGNvbmRpdGlvbiwgZGF0YSA9IGNvbmRpdGlvbmFsUHJvYkNvbnRyb2wsIGZvcm1hdCA9ICJwcm9wb3J0aW9uIikKIyMgR3JlYXRlciBvciBlcXVhbCA1MDogCnRhbGx5KH5mcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIHwgY29uZGl0aW9uLCBkYXRhID0gY29uZGl0aW9uYWxQcm9iQ29udHJvbCwgZm9ybWF0ID0gInByb3BvcnRpb24iKQoKYGBgCgojIyBCb3hwbG90IGZvciBmcmFjdHVyZSBzY29yZXMgdnMuIHZpYWJpbGl0eSBzY29yZSBzdW0gKDctNzApCmBgYHtyfQpncm91cGVkUHJvcG9ydGlvbkZyYWN0dXJlJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXI1MCkKZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZUdyZWF0ZXI1MCksIG1lZGlhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBtZWRpYW4gdmlhYmlsaXR5IHNjb3JlIGluIHJlbGF0aW9uIHRvIGJpbmFyeSBmcmFjdHVyZSB2YWx1ZSAoZ3JlYXRlciB0aGFuIDUwKSIsIAogICAgICAgeD0iQmluYXJ5IGZyYWN0dXJlIHZhbHVlIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiMCIgPSAiTm8gRnJhY3R1cmUiLCAiMSIgPSAiRnJhY3R1cmUiKSkgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKZyA8LSBnZ3Bsb3QoZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZSwgYWVzKGZhY3RvcihmcmFjdHVyZUdyZWF0ZXI1MCksIG1lZGlhbikpCmcgKyBnZW9tX2JveHBsb3QodmFyd2lkdGg9VCwgZmlsbD0icGx1bSIpICsgCiAgbGFicyhzdWJ0aXRsZT0iVGVhbSBtZWRpYW4gdmlhYmlsaXR5IHNjb3JlIGluIHJlbGF0aW9uIHRvIGJpbmFyeSBmcmFjdHVyZSB2YWx1ZSAoZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDUwKSIsIAogICAgICAgeD0iQmluYXJ5IGZyYWN0dXJlIHZhbHVlIiwKICAgICAgIHk9Ik51bWVyaWMgc3VtIG9mIHZpYWJpbGl0eSBtZWFzdXJlcyBxdWVzdGlvbnMgKHJhbmdlOiA3LTcwKSIpICsgc2NhbGVfeF9kaXNjcmV0ZShsYWJlbHM9YygiMCIgPSAiTm8gRnJhY3R1cmUiLCAiMSIgPSAiRnJhY3R1cmUiKSkgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWModHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwKSAKdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAgPC0gYXMubnVtZXJpYyh0cmVhdG1lbnRGcmFjdHVyZTEkZnJhY3R1cmVHcmVhdGVyRXF1YWw1MCkgCnRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCA8LSBhcy5udW1lcmljKHRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCkgCnRyZWF0bWVudEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWModHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApIApjb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXI1MCkKY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpjb250cm9sRnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlcjUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXI1MCkKY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwIDwtIGFzLm51bWVyaWMoY29udHJvbEZyYWN0dXJlMiRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpgYGAKCiMjIEFic29sdXRlIGNoYW5nZSBpbiBmcmFjdHVyZSBwcm9wb3J0aW9ucyBiZXR3ZWVuIGNvbmRpdGlvbnM6IApgYGB7cn0KdHJlYXRtZW50RnJhY3R1cmUkYWJzR3JlYXRlcjUwIDwtIGFicyh0cmVhdG1lbnRGcmFjdHVyZTIkZnJhY3R1cmVHcmVhdGVyNTAtdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlcjUwKQp0cmVhdG1lbnRGcmFjdHVyZSRhYnNFcXVhbEdyZWF0ZXI1MCA8LSBhYnModHJlYXRtZW50RnJhY3R1cmUyJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAtdHJlYXRtZW50RnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApCgpnIDwtIGdncGxvdCh0cmVhdG1lbnRGcmFjdHVyZSwgYWVzKGFic0dyZWF0ZXI1MCkpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24gKGZyYWN0dXJlID4uNTAiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24iKSArIAogIHlsYWIobGFiZWw9IkNvdW50IikgCgpnIDwtIGdncGxvdCh0cmVhdG1lbnRGcmFjdHVyZSwgYWVzKGFic0VxdWFsR3JlYXRlcjUwKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGJpbnM9NywgCiAgICAgICAgICAgICAgICAgICBjb2w9InBpbmsiLCAKICAgICAgICAgICAgICAgICAgIHNpemU9LjQpICsgCiAgbGFicyh0aXRsZT0iQWJzb2x1dGUgY2hhbmdlIGluIHRlYW0gZnJhY3R1cmUgc2NvcmUgaW4gdHJlYXRtZW50IGNvbmRpdGlvbiAoZnJhY3R1cmU+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIHRyZWF0bWVudCBjb25kaXRpb24iKSArIAogIHlsYWIobGFiZWw9IkNvdW50IikgCgpjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlcjUwIDwtIGFicyhjb250cm9sRnJhY3R1cmUkZnJhY3R1cmVHcmVhdGVyNTAtY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXI1MCkKZyA8LSBnZ3Bsb3QoY29udHJvbEZyYWN0dXJlLCBhZXMoYWJzR3JlYXRlcjUwKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGJpbnM9NywgCiAgICAgICAgICAgICAgICAgICBjb2w9InBpbmsiLCAKICAgICAgICAgICAgICAgICAgIHNpemU9LjQpICsgCiAgbGFicyh0aXRsZT0iQWJzb2x1dGUgY2hhbmdlIGluIHRlYW0gZnJhY3R1cmUgc2NvcmUgaW4gY29udHJvbCBjb25kaXRpb24gKGZyYWN0dXJlID4uNTApIiwgCiAgICAgICBmaWxsID0gIlJvdW5kIikgKyAKICB4bGFiKGxhYmVsPSJBYnNvbHV0ZSBjaGFuZ2UgaW4gdGVhbSBmcmFjdHVyZSBzY29yZSBpbiBjb250cm9sIGNvbmRpdGlvbiIpICsgCiAgeWxhYihsYWJlbD0iQ291bnQiKSAKCmNvbnRyb2xGcmFjdHVyZSRhYnNFcXVhbEdyZWF0ZXI1MCA8LSBhYnMoY29udHJvbEZyYWN0dXJlJGZyYWN0dXJlR3JlYXRlckVxdWFsNTAtY29udHJvbEZyYWN0dXJlMSRmcmFjdHVyZUdyZWF0ZXJFcXVhbDUwKQpnIDwtIGdncGxvdChjb250cm9sRnJhY3R1cmUsIGFlcyhhYnNFcXVhbEdyZWF0ZXI1MCkpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIChmcmFjdHVyZSA+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIikgKyAKICB5bGFiKGxhYmVsPSJDb3VudCIpIAoKY29udHJvbEZyYWN0dXJlJGFic0dyZWF0ZXJFcXVhbDUwIDwtIGFicyhjb250cm9sRnJhY3R1cmUkZnJhY3R1cmVHcmVhdGVyRXF1YWw1MC1jb250cm9sRnJhY3R1cmUxJGZyYWN0dXJlR3JlYXRlckVxdWFsNTApCmcgPC0gZ2dwbG90KGNvbnRyb2xGcmFjdHVyZSwgYWVzKGFicykpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTcGVjdHJhbCIpCmcgKyBnZW9tX2hpc3RvZ3JhbShiaW5zPTcsIAogICAgICAgICAgICAgICAgICAgY29sPSJwaW5rIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS40KSArIAogIGxhYnModGl0bGU9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIChmcmFjdHVyZSA+PS41MCkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9IkFic29sdXRlIGNoYW5nZSBpbiB0ZWFtIGZyYWN0dXJlIHNjb3JlIGluIGNvbnRyb2wgY29uZGl0aW9uIikgKyAKICB5bGFiKGxhYmVsPSJDb3VudCIpIAoKdHJlYXRtZW50RnJhY3R1cmVFcXVhbEdyZWF0ZXJBYnNTdW0gPC0gc3VtKHRyZWF0bWVudEZyYWN0dXJlJGFic0VxdWFsR3JlYXRlcjUwKSAKdHJlYXRtZW50RnJhY3R1cmVHcmVhdGVyQWJzU3VtIDwtIHN1bSh0cmVhdG1lbnRGcmFjdHVyZSRhYnNHcmVhdGVyNTApCgojIyBWaXN1YWxpemUgZGlmZmVyZW5jZXM6IAoKZGF0IDwtIGRhdGEuZnJhbWUoY2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiA9IGZhY3RvcihjKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiB0cmVhdG1lbnQgPj0uNTAiKSwgbGV2ZWxzPWMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID4uNTAiLCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+PS41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoOCwgMTkpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1kYXQsIGFlcyh4PWNoYW5nZXNQZXJGcmFjdHVyZURlZmluaXRpb24sIHk9ZnJhY3R1cmVWYWx1ZUNoYW5nZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCnAgPC0gZ2dwbG90bHkocCkKcAoKdHJlYXRtZW50RnJhY3R1cmVFcXVhbEdyZWF0ZXJBYnNTdW0gPC0gc3VtKHRyZWF0bWVudEZyYWN0dXJlJGFic0VxdWFsR3JlYXRlcjUwKSAKY29udHJvbEZyYWN0dXJlRXF1YWxHcmVhdGVyQWJzU3VtIDwtIHN1bShjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlckVxdWFsNTApCnRyZWF0bWVudEZyYWN0dXJlR3JlYXRlckFic1N1bSA8LSBzdW0odHJlYXRtZW50RnJhY3R1cmUkYWJzR3JlYXRlcjUwKQpjb250cm9sRnJhY3R1cmVHcmVhdGVyQWJzU3VtIDwtIHN1bShjb250cm9sRnJhY3R1cmUkYWJzR3JlYXRlcjUwKQoKZGF0IDwtIGRhdGEuZnJhbWUoY2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiA9IGZhY3RvcihjKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiBjb250cm9sID4uNTAiKSwgbGV2ZWxzPWMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID4uNTAiLCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIGNvbnRyb2wgPi41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoWCwgWCkpCgpwIDwtIGdncGxvdChkYXRhPWRhdCwgYWVzKHg9Y2hhbmdlc1BlckZyYWN0dXJlRGVmaW5pdGlvbiwgeT1mcmFjdHVyZVZhbHVlQ2hhbmdlKSkgKwogIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKcCA8LSBnZ3Bsb3RseShwKQpwCgpkYXQgPC0gZGF0YS5mcmFtZShjaGFuZ2VzUGVyRnJhY3R1cmVEZWZpbml0aW9uID0gZmFjdG9yKGMoIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gdHJlYXRtZW50ID49LjUwIiwiU3VtIG9mIGFic29sdXRlIGZyYWN0dXJlIGNoYW5nZSBpbiBjb250cm9sID49LjUwIiksIGxldmVscz1jKCJTdW0gb2YgYWJzb2x1dGUgZnJhY3R1cmUgY2hhbmdlIGluIHRyZWF0bWVudCA+PS41MCIsIlN1bSBvZiBhYnNvbHV0ZSBmcmFjdHVyZSBjaGFuZ2UgaW4gY29udHJvbCA+PS41MCIpKSwKICAgICAgICAgICAgICAgICAgZnJhY3R1cmVWYWx1ZUNoYW5nZSA9IGMoOCwgMTkpKQoKcCA8LSBnZ3Bsb3QoZGF0YT1kYXQsIGFlcyh4PWNoYW5nZXNQZXJGcmFjdHVyZURlZmluaXRpb24sIHk9ZnJhY3R1cmVWYWx1ZUNoYW5nZSkpICsKICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCnAgPC0gZ2dwbG90bHkocCkKcApgYGAKCmBgYHtyfQoKYGBgCgoKCgojIyBIaXN0b2dyYW0gY29tcGFyaXNvbnMgb2YgZnJhY3R1cmUgcmF0aW9zIGFjcm9zcyB0cmVhdG1lbnQsIGNvbnRyb2wgYW5kIGxlYXJuaW5nIGVmZmVjdCBjb25kaXRpb25zCgpgYGB7cn0KZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCwgYWVzKGZyYWN0dXJlKSkgKyAKICBnZW9tX2JhcihicmVha3M9c2VxKDAsIDEsIGJ5PTAuMjApLCAKICAgICAgICAgICAgICAgICBjb2w9InJlZCIsIAogICAgICAgICAgICAgICAgIGZpbGw9ImdyZWVuIiwgCiAgICAgICAgICAgICAgICAgYWxwaGE9LjIpICsgbGFicyh0aXRsZT0iRnJhY3R1cmUgcmF0aW9zOiB0cmVhdG1lbnQgY29uZGl0aW9uIikgKyBmYWNldF9ncmlkKGNvbmRpdGlvbiB+IHJlc3VsdHMuY29uZGl0aW9uKQoKZ2dwbG90KGRhdGE9Z3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZUNvbnRyb2wsIGFlcyhmcmFjdHVyZSkpICsgCiAgZ2VvbV9iYXIoYnJlYWtzPXNlcSgwLCAxLCBieT0wLjIwKSwgCiAgICAgICAgICAgICAgICAgY29sPSJyZWQiLCAKICAgICAgICAgICAgICAgICBmaWxsPSJncmVlbiIsIAogICAgICAgICAgICAgICAgIGFscGhhPS4yKSArIGxhYnModGl0bGU9IkZyYWN0dXJlIHJhdGlvczogY29udHJvbCByb3VuZCIpICsgZmFjZXRfZ3JpZChjb25kaXRpb24gfiByZXN1bHRzLmNvbmRpdGlvbikKCmdncGxvdChkYXRhPWdyb3VwZWRQcm9wb3J0aW9uRnJhY3R1cmVMRSwgYWVzKGZyYWN0dXJlKSkgKyAKICBnZW9tX2JhcihicmVha3M9c2VxKDAsIDEsIGJ5PTAuMjApLCAKICAgICAgICAgICAgICAgICBjb2w9InJlZCIsIAogICAgICAgICAgICAgICAgIGZpbGw9ImdyZWVuIiwgCiAgICAgICAgICAgICAgICAgYWxwaGE9LjIpICsgbGFicyh0aXRsZT0iRnJhY3R1cmUgcmF0aW9zOiBsZWFybmluZyBlZmZlY3QgY29uZGl0aW9uIikgKyBmYWNldF9ncmlkKHJlc3VsdHMuY29uZGl0aW9uIH4gcm91bmQpCgpgYGAKCiMjIEdyYXBocyBmb3IgbWVhbiBkaXN0cmJ1dGlvbiBwZXIgdHJlYXRtZW50IGNvbmRpdGlvbjogCgpgYGB7cn0KIyMgTWVhbiB2aWFiaWxpdHkgZGlzdHJpYnV0aW9uIGdyYXBoOiB0cmVhdG1lbnQgY29uZGl0aW9uLCBBIGdyb3VwIApiYXJmaWxsIDwtICIjNDI3MUFFIgpiYXJsaW5lcyA8LSAiIzFGMzU1MiIKIyMgTWVhbiBmb3IgdHJlYXRtZW50IGFuZCBBIGdyb3VwOiAjI2ZpbGwtaW4pIAptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QSA8LSBnZ3Bsb3QodHJlYXRtZW50QVN0YXRzLCBhZXMoeCA9IHN1bSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGJpbndpZHRoID0gNSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBiYXJsaW5lcywgZmlsbCA9IGJhcmZpbGwpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJNZWRpYW4gdmlhYmlsaXR5IHN1bSIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxMDAsIDIwKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzPWMoMCwgNzApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKG5hbWUgPSAiY291bnQiKSArCiAgZ2d0aXRsZSgiRnJlcXVlbmN5IG9mIHN1bSBvZiB2aWFiaWxpdHkgc2NvcmVzOiBOPSMjZmlsbC1pbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZT0xLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjZDNkM2QzIiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJUYWhvbWEiLCBmYWNlID0gImJvbGQiKSwKICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlRhaG9tYSIpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gIyNmaWxsLWluLCBzaXplID0gMSwgY29sb3VyID0gIiNGRjM3MjEiLAogICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKQptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QQoKIyMgTWVhbiB2aWFiaWxpdHkgZGlzdHJpYnV0aW9uIGdyYXBoOiB0cmVhdG1lbnQgY29uZGl0aW9uLCBBcHJpbWUgZ3JvdXAgCiMjIE1lYW4gZm9yIHRyZWF0bWVudCBjb25kaXRpb24sIEFwcmltZSBncm91cDogKGZpbGwtaW4pCm1lYW5EaXN0cmlidXRpb25UcmVhdG1lbnRBcCA8LSBnZ3Bsb3QodHJlYXRtZW50QXBTdGF0cywgYWVzKHggPSBzdW0pKSArCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmNvdW50Li4pLCBiaW53aWR0aCA9IDUsCiAgICAgICAgICAgICAgICAgY29sb3VyID0gYmFybGluZXMsIGZpbGwgPSBiYXJmaWxsKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG5hbWUgPSAiTWVkaWFuIHZpYWJpbGl0eSBzdW0iLAogICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMTAwLCAyMCksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cz1jKDAsIDcwKSkgKwogIHNjYWxlX3lfY29udGludW91cyhuYW1lID0gImNvdW50IikgKwogIGdndGl0bGUoIkZyZXF1ZW5jeSBvZiBzdW0gb2YgdmlhYmlsaXR5IHNjb3JlczpOPSMjZmlsbC1pbiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZT0xLCBjb2xvdXIgPSAiYmxhY2siKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICIjZDNkM2QzIiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhbWlseSA9ICJUYWhvbWEiLCBmYWNlID0gImJvbGQiKSwKICAgICAgICB0ZXh0PWVsZW1lbnRfdGV4dChmYW1pbHk9IlRhaG9tYSIpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpLAogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChjb2xvdXI9ImJsYWNrIiwgc2l6ZSA9IDkpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gIyNmaWxsLWluLCBzaXplID0gMSwgY29sb3VyID0gIiNGRjM3MjEiLAogICAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKQptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QXAKCiMjIE1lYW4gdmlhYmlsaXR5IGRpc3RyaWJ1dGlvbiBncmFwaDogdHJlYXRtZW50IGNvbmRpdGlvbiwgQiBncm91cCAKIyMgTWVhbiBmb3IgdHJlYXRtZW50IGNvbmRpdGlvbiwgQiBncm91cDogCmJhcmZpbGwgPC0gIiM0MjcxQUUiCmJhcmxpbmVzIDwtICIjMUYzNTUyIgptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QiA8LSBnZ3Bsb3QodHJlYXRtZW50QlN0YXRzLCBhZXMoeCA9IHN1bSkpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uY291bnQuLiksIGJpbndpZHRoID0gNSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBiYXJsaW5lcywgZmlsbCA9IGJhcmZpbGwpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobmFtZSA9ICJNZWRpYW4gdmlhYmlsaXR5IHN1bSBcbiBhY3Jvc3MgYWxsIHRlYW1zIGluIG1hc2tlZCByb3VuZCIsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCA5OCwgMTQpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHM9Yyg3LCA3MCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobmFtZSA9ICJjb3VudCIpICsKICBnZ3RpdGxlKCJGcmVxdWVuY3kgb2Ygc3VtIG9mIHZpYWJpbGl0eSBzY29yZXM6IG1hc2tlZCBjb25kaXRpb24sIE49IyNmaWxsLWluIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplPTEsIGNvbG91ciA9ICJibGFjayIpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gIiNkM2QzZDMiKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFtaWx5ID0gIlRhaG9tYSIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIHRleHQ9ZWxlbWVudF90ZXh0KGZhbWlseT0iVGFob21hIiksCiAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplID0gOSksCiAgICAgICAgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KGNvbG91cj0iYmxhY2siLCBzaXplID0gOSkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAjI2ZpbGwtaW4sIHNpemUgPSAxLCBjb2xvdXIgPSAiI0ZGMzcyMSIsCiAgICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpIAptZWFuRGlzdHJpYnV0aW9uVHJlYXRtZW50QgpgYGAKCiMjIENoYXQgZGF0YTogCmBgYHtyfQpjaGF0RmlsZXMgPSBsYXBwbHkoY29tcGxldGVCYXRjaGVzLCBmdW5jdGlvbihiYXRjaCl7CiAgICBjaGF0RmlsZSA9IHJlYWRfanNvbihwYXN0ZShkYXRhUGF0aCxiYXRjaCwiY2hhdHMuanNvbiIsc2VwPSIvIiksIHNpbXBsaWZ5VmVjdG9yID0gVFJVRSkKICAgIHJldHVybihmbGF0dGVuKGNoYXRGaWxlLCByZWN1cnNpdmUgPSBUUlVFKSkKICB9KQoKYWxsQ2hhdEZpbGVzIDwtIHBseXI6OmxkcGx5KGNoYXRGaWxlcywgZGF0YS5mcmFtZSkKY2hhdEZyZXEgPC0gYWxsQ2hhdEZpbGVzICAlPiUKICBncm91cF9ieShyb3VuZCwgcm9vbSwgYmF0Y2gpICU+JSAKICBkcGx5cjo6c3VtbWFyaXNlKG49bigpKSAlPiUgCiAgZmlsdGVyKG4+MSwgcm91bmQ8PTIpCgojIyBGaWx0ZXIgb24gcm91bmQgPD0yLCBiZWNhdXNlIHJvdW5kIDMgaW4gYWxsIGJ1dCBvbmUgY2FzZSBpcyBvbmx5IGluY2x1ZGVzICJYIGhhcyBsZWZ0IGNoYXQgcm9vbSIgCgojIEhpc3RvZ3JhbSBncm91cGVkIGJ5IHJvdW5kOiAKZyA8LSBnZ3Bsb3QoY2hhdEZyZXEsIGFlcyhuKSkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlNwZWN0cmFsIikKZyArIGdlb21faGlzdG9ncmFtKGFlcyhmaWxsPWZhY3Rvcihyb3VuZCkpLCAKICAgICAgICAgICAgICAgICAgIGJpbnM9NSwgCiAgICAgICAgICAgICAgICAgICBjb2w9ImJsYWNrIiwgCiAgICAgICAgICAgICAgICAgICBzaXplPS4xKSArICAgIyBjaGFuZ2UgbnVtYmVyIG9mIGJpbnMKICBsYWJzKHRpdGxlPSJIaXN0b2dyYW0gb2YgdGhlIG51bWJlciBvZiBjaGF0IGxpbmVzIHBlciB0ZWFtIChpbmNsdWRlcyB0ZWFtcyB3aXRoIG49MSkiLCAKICAgICAgIGZpbGwgPSAiUm91bmQiKSArIAogIHhsYWIobGFiZWw9Ik51bWJlciBvZiBsaW5lcyBmcm9tIGNoYXQgZGF0YSBwZXIgdGVhbSIpICsgCiAgeWxhYihsYWJlbD0iQ291bnQiKSAKc3RhdHMkcm9vbSA8LSB1bmxpc3Qoc3RhdHMkcm9vbSkgCmNoYXRGcmVxU3RhdHMgPC0gcmlnaHRfam9pbih4PWNoYXRGcmVxLCB5PXN0YXRzKQoKCiMjIEV4cG9ydCBjaGF0IGRhdGEgZm9yIE1hdjogCndyaXRlLmNzdihhbGxDaGF0RmlsZXMsIGZpbGUgPSAiYWxsQ2hhdEZpbGVzLmNzdiIpCgpgYGAKCiMjIENvbmRpdGlvbmFsIHByb2JhYmlsaXRpZXM6IApgYGB7cn0KZ3JvdXBlZFByb3BvcnRpb25GcmFjdHVyZVRyZWF0bWVudCAlPiUgCiAgZ3JvdXBfYnkoY29uZGl0aW9uKSAlPiUgCiAgc3VtbWFyaXNlKG49bigpLCBjb3VudD1jb3VudChmcmFjdHVyZSkpIAoKIyBQKEYzfEYxKSAKcDEgPC0gIDE5IC8gMzQKCiMgUChub3RGM3xGMSkgCnAyIDwtICAxNSAvIDM0CgojIFAoRjN8RjEpCnAzIDwtIDI0IC8gMzQKCiMjIFAobm90RjN8RjEpCnA0IDwtIDEwIC8gMzQKCiAgIyBQcmludCBvdXQgdGhlIHByb2JhYmlsaXRpZXMKcm91bmQoYyhwMSwgcDIsIHAzLCBwNCksIGRpZ2l0cyA9IDIpICAKYGBgCgojIyBDSEkgU3F1YXJlZDogCmBgYHtyfQoKYGBgCgoK